package it.giuseppetrisciuoglio.lyrics.processor.album;

import it.giuseppetrisciuoglio.lyrics.persistence.entity.Album;
import it.giuseppetrisciuoglio.lyrics.persistence.entity.Artista;
import it.giuseppetrisciuoglio.lyrics.persistence.entity.MetaDataInfoAlbum;
import it.giuseppetrisciuoglio.lyrics.persistence.repository.AlbumRepository;
import it.giuseppetrisciuoglio.lyrics.persistence.repository.ArtistaRepository;
import it.giuseppetrisciuoglio.lyrics.persistence.repository.MetaDataInfoAlbumRepository;
import it.giuseppetrisciuoglio.lyrics.utils.DateUtilies;

import java.io.IOException;
import java.util.Collection;
import java.util.List;

import org.musicbrainz.android.api.data.Label;
import org.musicbrainz.android.api.data.Release;
import org.musicbrainz.android.api.data.WebLink;
import org.musicbrainz.android.api.webservice.MusicBrainzWebClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import de.umass.lastfm.Authenticator;
import de.umass.lastfm.ImageSize;

@Service
public class AlbumMetaDataInfoProcessor {

	@Autowired
	private ArtistaRepository artistaRepository;

	@Autowired
	private AlbumRepository albumRepository;

	@Autowired
	private MetaDataInfoAlbumRepository metaDataInfoAlbumRepository;

	@Value("${lastFM.APIKey}")
	private String apiKey;

	@Value("${lastFM.secret}")
	private String secret;
	
	@Value("${http.userAgent}")
	private String userAgent;
	
	private final transient Logger log = LoggerFactory.getLogger(getClass());

	private void init() {
		log.debug("init(): call authenticator");
		String token = Authenticator.getToken(apiKey);
		log.debug("init(): token authenticator={}", token);
		Authenticator.getSession(token, token, secret);
	}

	public void process(Long artistaId) {
		log.debug("process(): artistaId={}", artistaId);
		Artista artista = artistaRepository.findOne(artistaId);
		List<Album> albums = albumRepository.findAlbumsByArtista(artista);
		for (Album album : albums) {
			createMetaDataInfoAlbum(album, artista);
		}
	}

	private void createMetaDataInfoAlbum(Album album, Artista artista) {
		de.umass.lastfm.Album albumFM = getAlbum(album, artista);
		createAlbumMetaDataInfoAlbum(albumFM, album);
		Release release = getRelease(album);
		Collection<String> labels = release.getLabels();
		for (String label : labels) {
			createLabelRecordsMetaDataInfoAlbum(label, album);
			break;
		}
	}
	
	private void createLabelRecordsMetaDataInfoAlbum(String label, Album album) {
		saveMetaDataInfoAlbum(album, label, MetaDataInfoAlbum.TIPO_ALBUM_LABEL_NAME);
	}
	
	private void createAlbumMetaDataInfoAlbum(de.umass.lastfm.Album albumFM, Album album) {
		saveMetaDataInfoAlbum(album, DateUtilies.toString(albumFM.getReleaseDate()), MetaDataInfoAlbum.TIPO_ALBUM_RELEASE_DATE);
		saveMetaDataInfoAlbum(album, albumFM.getUrl(), MetaDataInfoAlbum.TIPO_ALBUM_LASTFM_URL);
		saveMetaDataInfoAlbum(album, albumFM.getImageURL(ImageSize.EXTRALARGE), MetaDataInfoAlbum.TIPO_ALBUM_COVER_URL);
	}
	
	private void saveMetaDataInfoAlbum(Album album, String value, String tipo) {
		if (value == null || value.isEmpty())
			return;
		log.debug("value={}",value);
		MetaDataInfoAlbum infoAlbum = metaDataInfoAlbumRepository.findByTipoAndAlbum(tipo, album);
		if (infoAlbum == null){
			infoAlbum = new MetaDataInfoAlbum();
		}
		infoAlbum.setAlbum(album);
		infoAlbum.setTipo(tipo);
		infoAlbum.setValore(value);
		metaDataInfoAlbumRepository.save(infoAlbum);
	}

	private de.umass.lastfm.Album getAlbum(Album album, Artista artista){
		de.umass.lastfm.Album albumFM = de.umass.lastfm.Album.getInfo(artista.getNome(), album.getTitolo(), apiKey);
		log.debug("process(): albumFM={}", albumFM);
		return albumFM;
	}
	
	private Release getRelease(Album album){
		try {
			MusicBrainzWebClient musicBrainzWebClient = new MusicBrainzWebClient(userAgent);
			return musicBrainzWebClient.lookupRelease(album.getMbid());
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	private Label getLabel(String mbid){
		try {
			MusicBrainzWebClient musicBrainzWebClient = new MusicBrainzWebClient(userAgent);
			return musicBrainzWebClient.lookupLabel(mbid);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	private String getOfficialSite(List<WebLink> links){
		for (WebLink webLink : links) {
			if (webLink.getType().equalsIgnoreCase("official site")){
				return webLink.getUrl();
			}
		}
		return null;
	}

}
